import jwt from 'jsonwebtoken';
import { JwtPayload, UserRole } from '@/types';

const JWT_SECRET = process.env['JWT_SECRET'] || 'your-jwt-secret-key';
const JWT_EXPIRES_IN = process.env['JWT_EXPIRES_IN'] || '24h';

// 角色映射到数字
const roleToNumber: Record<UserRole, number> = {
  [UserRole.GUEST]: 0,
  [UserRole.USER]: 1,
  [UserRole.VIP]: 2,
  [UserRole.ADMIN]: 3,
  [UserRole.SUPER_ADMIN]: 4,
};

// 数字映射到角色
const numberToRole: Record<number, UserRole> = {
  0: UserRole.GUEST,
  1: UserRole.USER,
  2: UserRole.VIP,
  3: UserRole.ADMIN,
  4: UserRole.SUPER_ADMIN,
};

export const generateToken = (
  userId: string,
  username: string,
  role: UserRole
): string => {
  // 极简payload，只保留最必要信息
  const payload = {
    i: userId, // 用户ID
    n: username, // 用户名
    r: roleToNumber[role], // 角色用数字表示
  };
  return jwt.sign(payload, JWT_SECRET, {
    expiresIn: JWT_EXPIRES_IN,
    algorithm: 'HS256',
  } as jwt.SignOptions);
};

export const verifyToken = (token: string): JwtPayload => {
  try {
    const decoded = jwt.verify(token, JWT_SECRET) as any;
    // 转换回标准格式
    return {
      userId: decoded.i,
      username: decoded.n,
      role: numberToRole[decoded.r] || UserRole.USER,
      iat: decoded.iat,
      exp: decoded.exp,
    };
  } catch (error) {
    throw new Error('Invalid token');
  }
};

export const decodeToken = (token: string): JwtPayload | null => {
  try {
    const decoded = jwt.decode(token) as any;
    if (!decoded) return null;

    // 转换回标准格式
    return {
      userId: decoded.i,
      username: decoded.n,
      role: numberToRole[decoded.r] || UserRole.USER,
      iat: decoded.iat,
      exp: decoded.exp,
    };
  } catch (error) {
    return null;
  }
};

// 角色权限检查
export const hasPermission = (
  userRole: UserRole,
  requiredRole: UserRole
): boolean => {
  const roleHierarchy: Record<UserRole, number> = {
    [UserRole.GUEST]: 0,
    [UserRole.USER]: 1,
    [UserRole.VIP]: 2,
    [UserRole.ADMIN]: 3,
    [UserRole.SUPER_ADMIN]: 4,
  };

  return roleHierarchy[userRole] >= roleHierarchy[requiredRole];
};
